﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TCG.Engine.Core;
using TCG.Engine.Libraries;

namespace TCG.Engine.WiningConditions
{
    public class MatchResult
    {
        public bool GameOver { get; set; }
        public Player Winner { get; set; }
        public bool IsDraw { get; set; }
    }

    public enum WCValueCompareOperations
    {
        gt,
        lt,
        eq,
        gteq,
        lteq
    }

    public interface IWinningCondition
    {
        MatchResult Validate(MoveContext mc);
    }

    public abstract class WCOperation : IWinningCondition
    {
        protected IWinningCondition left, right;

        public WCOperation(IWinningCondition leftPart, IWinningCondition rightPart)
        {
            left = leftPart;
            right = rightPart;
        }

        public abstract MatchResult Validate(MoveContext mc);
    }

    public abstract class WCValueBased : IWinningCondition
    {
        public int Value { get; set; }
        public TargerInfo Target { get; set; }

        protected MatchResult Validate(MoveContext mc, int player1Value, int player2Value, WCValueCompareOperations comparator)
        {
            var result = new MatchResult();

            Func<bool> firstFunc = null;
            Func<bool> secondFunc = null;
            Func<bool> thirdFunc = null;

            switch (comparator)
            {
                case WCValueCompareOperations.lt:
                    firstFunc = () => player1Value < Value && player2Value < Value;
                    secondFunc = () => player1Value < Value;
                    thirdFunc = () => player2Value < Value;
                    break;

                case WCValueCompareOperations.lteq:
                    firstFunc = () => player1Value <= Value && player2Value <= Value;
                    secondFunc = () => player1Value <= Value;
                    thirdFunc = () => player2Value <= Value;
                    break;

                case WCValueCompareOperations.gt:
                    firstFunc = () => player1Value > Value && player2Value > Value;
                    secondFunc = () => player1Value > Value;
                    thirdFunc = () => player2Value > Value;
                    break;

                case WCValueCompareOperations.gteq:
                    firstFunc = () => player1Value >= Value && player2Value >= Value;
                    secondFunc = () => player1Value >= Value;
                    thirdFunc = () => player2Value >= Value;
                    break;

                case WCValueCompareOperations.eq:
                    firstFunc = () => player1Value == Value && player2Value == Value;
                    secondFunc = () => player1Value == Value;
                    thirdFunc = () => player2Value == Value;
                    break;
            }

            if (firstFunc())
            {
                result.GameOver = true;
                result.Winner = null;
                result.IsDraw = true;
                return result;
            }
            if (secondFunc() && Target == TargerInfo.Self && mc.ActivePlayer == mc.Player1)
            {
                result.GameOver = true;
                result.Winner = mc.Player1;
            }
            if (secondFunc() && Target == TargerInfo.Enemy && mc.ActivePlayer == mc.Player2)
            {
                result.GameOver = true;
                result.Winner = mc.Player2;
            }
            if (thirdFunc() && Target == TargerInfo.Self && mc.ActivePlayer == mc.Player2)
            {
                result.GameOver = true;
                result.Winner = mc.Player2;
            }
            if (thirdFunc() && Target == TargerInfo.Enemy && mc.ActivePlayer == mc.Player1)
            {
                result.GameOver = true;
                result.Winner = mc.Player1;
            }

            return result;
        }

        public abstract MatchResult Validate(MoveContext mc);

        public WCValueBased(int value, TargerInfo target)
        {
            Value = value;
            Target = target;
        }

        public WCValueBased() { }
    }

    public class WCOr : WCOperation
    {
        public WCOr(IWinningCondition leftPart, IWinningCondition rightPart) :
            base(leftPart, rightPart) { }

        public override MatchResult Validate(MoveContext mc)
        {
            var leftResult = left.Validate(mc);
            if (leftResult.GameOver)
                return leftResult;

            var rightResult = right.Validate(mc);
            if (rightResult.GameOver)
                return rightResult;

            return new MatchResult();
        }
    }

    public class WCAnd : WCOperation
    {
        public WCAnd(IWinningCondition leftPart, IWinningCondition rightPart) :
            base(leftPart, rightPart) { }

        public override MatchResult Validate(MoveContext mc)
        {
            var leftResult = left.Validate(mc);
            var rightResult = right.Validate(mc);

            var result = new MatchResult();
            if (leftResult.GameOver && rightResult.GameOver)
            {
                result.GameOver = true;
                if (leftResult.IsDraw && rightResult.IsDraw)
                    result.IsDraw = true;
                else
                    result.Winner = leftResult.Winner;

                return result;
            }

            return result;
        }
    }

    public class WCReduceLife : WCValueBased
    {
        public WCReduceLife(int value, TargerInfo target) : base(value, target) { }

        public override MatchResult Validate(MoveContext mc)
        {
            return Validate(mc, mc.Player1.Life, mc.Player2.Life, WCValueCompareOperations.lteq);
        }
    }

    public class WCGrowLife : WCValueBased
    {
        public WCGrowLife(int value, TargerInfo target) : base(value, target) { }

        public override MatchResult Validate(MoveContext mc)
        {
            return Validate(mc, mc.Player1.Life, mc.Player2.Life, WCValueCompareOperations.gteq);
        }
    }

    public class WCCollectGold : WCValueBased
    {
        public WCCollectGold(int value, TargerInfo target) : base(value, target) { }

        public override MatchResult Validate(MoveContext mc)
        {
            return Validate(mc, mc.Player1.Gold, mc.Player2.Gold, WCValueCompareOperations.gteq);
        }
    }

    public class WCCollectMana : WCValueBased
    {
        public WCCollectMana(int value, TargerInfo target) : base(value, target) { }

        public override MatchResult Validate(MoveContext mc)
        {
            return Validate(mc, mc.Player1.Mana, mc.Player2.Mana, WCValueCompareOperations.gteq);
        }
    }

}
